package com.lucifer.treasure.enchant.effect;

import com.lucifer.treasure.registry.EnchantRegistry;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.minecraft.enchantment.EnchantmentEffectContext;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.enchantment.EnchantmentLevelBasedValue;
import net.minecraft.enchantment.effect.EnchantmentEntityEffect;
import net.minecraft.entity.Entity;
import net.minecraft.entity.ExperienceOrbEntity;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;

import java.util.List;

public record MagnetEnchantmentEffect(EnchantmentLevelBasedValue range) implements EnchantmentEntityEffect {
    public static final MapCodec<MagnetEnchantmentEffect> CODEC = RecordCodecBuilder.mapCodec(instance ->
            instance.group(
                    EnchantmentLevelBasedValue.CODEC.fieldOf("range").forGetter(MagnetEnchantmentEffect::range)
            ).apply(instance, MagnetEnchantmentEffect::new)
    );

    // 基础范围和每级增加的范围
    private static final double BASE_HORIZONTAL_RANGE = 4.0;
    private static final double RANGE_PER_LEVEL = 4.0;
    private static final double VERTICAL_RANGE = 4.0;

    // 吸引力强度
    private static final double ATTRACTION_SPEED = 0.15;

    public static void initialize() {
        ServerTickEvents.END_SERVER_TICK.register(server -> {
            // 首先检查配置是否启用此附魔
            if (!EnchantRegistry.isEnchantEnabled("magnet")) {
                return;
            }

            server.getPlayerManager().getPlayerList().forEach(player -> {
                if (player.isSpectator()) {
                    return;
                }

                // 检查玩家装备的所有物品是否有Magnet附魔
                int maxLevel = getMagnetLevel(player);
                if (maxLevel <= 0) {
                    return;
                }

                // 计算吸引范围
                double horizontalRange = BASE_HORIZONTAL_RANGE + RANGE_PER_LEVEL * maxLevel;

                // 创建搜索区域
                Vec3d playerPos = player.getPos();
                Box searchBox = new Box(
                        playerPos.x - horizontalRange, playerPos.y - VERTICAL_RANGE, playerPos.z - horizontalRange,
                        playerPos.x + horizontalRange, playerPos.y + VERTICAL_RANGE, playerPos.z + horizontalRange
                );

                // 吸引掉落物品
                attractItems(player, searchBox);

                // 吸引经验球
                attractExperience(player, searchBox);
            });
        });
    }

    /**
     * 获取玩家身上Magnet附魔的最高等级
     */
    private static int getMagnetLevel(PlayerEntity player) {
        int maxLevel = 0;

        // 检查主手、副手和盔甲
        for (ItemStack stack : player.getArmorItems()) {
            maxLevel = Math.max(maxLevel, getMagnetLevelFromStack(stack));
        }
        maxLevel = Math.max(maxLevel, getMagnetLevelFromStack(player.getMainHandStack()));
        maxLevel = Math.max(maxLevel, getMagnetLevelFromStack(player.getOffHandStack()));

        return maxLevel;
    }

    /**
     * 从物品栈获取Magnet附魔等级
     */
    private static int getMagnetLevelFromStack(ItemStack stack) {
        if (stack.isEmpty()) {
            return 0;
        }

        var enchantments = EnchantmentHelper.getEnchantments(stack);
        int maxLevel = 0;

        for (var entry : enchantments.getEnchantments()) {
            if (entry.getKey().isPresent()) {
                String enchantmentId = entry.getKey().get().getValue().toString();
                if (enchantmentId.equals("lucifer_treasure:magnet")) {
                    maxLevel = Math.max(maxLevel, enchantments.getLevel(entry));
                }
            }
        }

        return maxLevel;
    }

    /**
     * 吸引掉落物品
     */
    private static void attractItems(PlayerEntity player, Box searchBox) {
        World world = player.getWorld();
        List<ItemEntity> items = world.getEntitiesByClass(ItemEntity.class, searchBox,
                item -> item.isAlive() && !item.hasNoGravity() && item.age > 10);

        for (ItemEntity item : items) {
            // 计算从物品到玩家的向量
            Vec3d playerPos = player.getPos().add(0, 0.5, 0); // 稍微抬高到玩家中心
            Vec3d itemPos = item.getPos();
            Vec3d direction = playerPos.subtract(itemPos).normalize();

            // 计算距离，距离越近吸引力越强
            double distance = itemPos.distanceTo(playerPos);
            double attractionMultiplier = Math.min(1.0, 3.0 / Math.max(distance, 1.0));

            // 应用吸引力
            Vec3d attraction = direction.multiply(ATTRACTION_SPEED * attractionMultiplier);
            item.addVelocity(attraction.x, attraction.y, attraction.z);

            // 限制最大速度，避免物品飞得太快
            Vec3d velocity = item.getVelocity();
            double maxSpeed = 0.5;
            if (velocity.length() > maxSpeed) {
                velocity = velocity.normalize().multiply(maxSpeed);
                item.setVelocity(velocity);
            }
        }
    }

    /**
     * 吸引经验球
     */
    private static void attractExperience(PlayerEntity player, Box searchBox) {
        World world = player.getWorld();
        List<ExperienceOrbEntity> expOrbs = world.getEntitiesByClass(ExperienceOrbEntity.class, searchBox,
                orb -> orb.isAlive());

        for (ExperienceOrbEntity orb : expOrbs) {
            // 计算从经验球到玩家的向量
            Vec3d playerPos = player.getPos().add(0, 0.5, 0);
            Vec3d orbPos = orb.getPos();
            Vec3d direction = playerPos.subtract(orbPos).normalize();

            // 经验球吸引力比物品稍强
            double distance = orbPos.distanceTo(playerPos);
            double attractionMultiplier = Math.min(1.0, 4.0 / Math.max(distance, 1.0));

            // 应用吸引力
            Vec3d attraction = direction.multiply(ATTRACTION_SPEED * attractionMultiplier * 1.2);
            orb.addVelocity(attraction.x, attraction.y, attraction.z);

            // 限制最大速度
            Vec3d velocity = orb.getVelocity();
            double maxSpeed = 0.6;
            if (velocity.length() > maxSpeed) {
                velocity = velocity.normalize().multiply(maxSpeed);
                orb.setVelocity(velocity);
            }
        }
    }

    @Override
    public void apply(ServerWorld world, int level, EnchantmentEffectContext context, Entity target, Vec3d pos) {
        // 主要逻辑在服务器tick事件中处理
        // 这个方法保留用于其他可能的触发方式
    }

    @Override
    public MapCodec<? extends EnchantmentEntityEffect> getCodec() {
        return CODEC;
    }
} 